winsafe\comctl\handles/himagelist.rs
1#![allow(non_camel_case_types, non_snake_case)]
2
3use crate::co;
4use crate::comctl::{ffi, iterators::*, privs::*};
5use crate::decl::*;
6use crate::guard::*;
7use crate::kernel::privs::*;
8use crate::prelude::*;
9
10handle! { HIMAGELIST;
11 /// Handle to an
12 /// [image list](https://learn.microsoft.com/en-us/windows/win32/controls/image-lists).
13}
14
15impl HIMAGELIST {
16 /// Returns an iterator over all icons in the image list, by calling
17 /// [`HIMAGELIST::ExtractIcon`](crate::HIMAGELIST::ExtractIcon) for each
18 /// one.
19 ///
20 /// # Examples
21 ///
22 /// Collecting the icons into a [`Vec`](std::vec::Vec):
23 ///
24 /// ```no_run
25 /// use winsafe::{self as w, prelude::*};
26 ///
27 /// let himgl: w::HIMAGELIST; // initialized somewhere
28 /// # let himgl = w::HIMAGELIST::NULL;
29 ///
30 /// let icons = himgl.iter()
31 /// .collect::<w::HrResult<Vec<_>>>()?;
32 /// # w::HrResult::Ok(())
33 /// ```
34 #[must_use]
35 pub fn iter(&self) -> impl Iterator<Item = HrResult<DestroyIconGuard>> + '_ {
36 HimagelistIter::new(self)
37 }
38
39 /// [`ImageList_Add`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_add)
40 /// function.
41 ///
42 /// A copy of the bitmap is made and stored in the image list, so you're
43 /// free to release the original bitmap.
44 pub fn Add(&self, hbmp_image: &HBITMAP, hbmp_mask: Option<&HBITMAP>) -> HrResult<u32> {
45 match unsafe {
46 ffi::ImageList_Add(
47 self.ptr(),
48 hbmp_image.ptr(),
49 hbmp_mask.map_or(std::ptr::null_mut(), |h| h.ptr()),
50 )
51 } {
52 -1 => Err(co::HRESULT::E_FAIL),
53 idx => Ok(idx as _),
54 }
55 }
56
57 /// [`ImageList_AddIcon`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_addicon)
58 /// macro.
59 ///
60 /// A copy of the icon is made and stored in the image list, so you're free
61 /// to release the original icon.
62 pub fn AddIcon(&self, hicon: &HICON) -> HrResult<u32> {
63 match unsafe { ffi::ImageList_ReplaceIcon(self.ptr(), -1, hicon.ptr()) } {
64 -1 => Err(co::HRESULT::E_FAIL),
65 idx => Ok(idx as _),
66 }
67 }
68
69 /// [`ImageList_AddMasked`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_addmasked)
70 /// function.
71 ///
72 /// A copy of the bitmap is made and stored in the image list, so you're
73 /// free to release the original bitmap.
74 pub fn AddMasked(&self, hbmp_image: &HBITMAP, color_mask: COLORREF) -> HrResult<u32> {
75 match unsafe { ffi::ImageList_AddMasked(self.ptr(), hbmp_image.ptr(), color_mask.into()) } {
76 -1 => Err(co::HRESULT::E_FAIL),
77 idx => Ok(idx as _),
78 }
79 }
80
81 /// [`ImageList_BeginDrag`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_begindrag)
82 /// function.
83 ///
84 /// In the original C implementation, you must call
85 /// [`ImageList_EndDrag`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_enddrag)
86 /// as a cleanup operation.
87 ///
88 /// Here, the cleanup is performed automatically, because `BeginDrag`
89 /// returns an
90 /// [`ImageListEndDragGuard`](crate::guard::ImageListEndDragGuard), which
91 /// automatically calls `ImageList_EndDrag` when the guard goes out of
92 /// scope. You must, however, keep the guard alive, otherwise the cleanup
93 /// will be performed right away.
94 ///
95 /// # Examples
96 ///
97 /// ```no_run
98 /// use winsafe::{self as w, prelude::*};
99 ///
100 /// let himgl: w::HIMAGELIST; // initialized somewhere
101 /// # let himgl = w::HIMAGELIST::NULL;
102 ///
103 /// let _drag = himgl.BeginDrag(0, w::POINT::new())?; // keep guard alive
104 /// # w::HrResult::Ok(())
105 /// ```
106 pub fn BeginDrag(&self, itrack: u32, hotspot: POINT) -> HrResult<ImageListEndDragGuard<'_>> {
107 unsafe {
108 match ffi::ImageList_BeginDrag(self.ptr(), itrack as _, hotspot.x, hotspot.y) {
109 0 => Err(co::HRESULT::E_FAIL),
110 _ => Ok(ImageListEndDragGuard::new()),
111 }
112 }
113 }
114
115 /// [`ImageList_Create`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_create)
116 /// function.
117 ///
118 /// # Examples
119 ///
120 /// ```no_run
121 /// use winsafe::{self as w, prelude::*, co};
122 ///
123 /// let himgl = w::HIMAGELIST::Create(
124 /// w::SIZE::with(16, 16),
125 /// co::ILC::COLOR32,
126 /// 1,
127 /// 1,
128 /// )?;
129 ///
130 /// // ImageList_Destroy() automatically called
131 /// # w::HrResult::Ok(())
132 /// ```
133 #[must_use]
134 pub fn Create(
135 image_sz: SIZE,
136 flags: co::ILC,
137 initial_size: i32,
138 grow_size: i32,
139 ) -> HrResult<ImageListDestroyGuard> {
140 unsafe {
141 match ptr_to_option_handle(ffi::ImageList_Create(
142 image_sz.cx,
143 image_sz.cy,
144 flags.raw(),
145 initial_size,
146 grow_size,
147 )) {
148 None => Err(co::HRESULT::E_FAIL),
149 Some(h) => Ok(ImageListDestroyGuard::new(h)),
150 }
151 }
152 }
153
154 /// [`ImageList_DragMove`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_dragmove)
155 /// function.
156 pub fn DragMove(&self, x: i32, y: i32) -> HrResult<()> {
157 match unsafe { ffi::ImageList_DragMove(self.ptr(), x, y) } {
158 0 => Err(co::HRESULT::E_FAIL),
159 _ => Ok(()),
160 }
161 }
162
163 /// [`ImageList_DragShowNolock`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_dragshownolock)
164 /// function.
165 pub fn DragShowNolock(show: bool) -> HrResult<()> {
166 match unsafe { ffi::ImageList_DragShowNolock(show as _) } {
167 0 => Err(co::HRESULT::E_FAIL),
168 _ => Ok(()),
169 }
170 }
171
172 /// [`ImageList_Draw`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_draw)
173 /// function.
174 pub fn Draw(&self, index: u32, hdc_dest: &HDC, dest: POINT, style: co::ILD) -> HrResult<()> {
175 match unsafe {
176 ffi::ImageList_Draw(self.ptr(), index as _, hdc_dest.ptr(), dest.x, dest.y, style.raw())
177 } {
178 0 => Err(co::HRESULT::E_FAIL),
179 _ => Ok(()),
180 }
181 }
182
183 /// [`ImageList_DrawEx`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_drawex)
184 /// function.
185 pub fn DrawEx(
186 &self,
187 index: u32,
188 hdc_dest: &HDC,
189 dest: POINT,
190 img_portion: Option<SIZE>,
191 background_color: ClrDefNone,
192 foreground_color: ClrDefNone,
193 style: co::ILD,
194 ) -> HrResult<()> {
195 match unsafe {
196 ffi::ImageList_DrawEx(
197 self.ptr(),
198 index as _,
199 hdc_dest.ptr(),
200 dest.x,
201 dest.y,
202 img_portion.unwrap_or_default().cx,
203 img_portion.unwrap_or_default().cy,
204 background_color.as_u32(),
205 foreground_color.as_u32(),
206 style.raw(),
207 )
208 } {
209 0 => Err(co::HRESULT::E_FAIL),
210 _ => Ok(()),
211 }
212 }
213
214 /// [`ImageList_Duplicate`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_duplicate)
215 /// function.
216 pub fn Duplicate(&self) -> HrResult<ImageListDestroyGuard> {
217 unsafe {
218 match ptr_to_option_handle(ffi::ImageList_Duplicate(self.ptr())) {
219 None => Err(co::HRESULT::E_FAIL),
220 Some(h) => Ok(ImageListDestroyGuard::new(h)),
221 }
222 }
223 }
224
225 /// [`ImageList_ExtractIcon`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_extracticon)
226 /// macro.
227 ///
228 /// A copy of the stored icon is returned.
229 #[must_use]
230 pub fn ExtractIcon(&self, index: u32) -> HrResult<DestroyIconGuard> {
231 self.GetIcon(index, co::ILD::NORMAL)
232 }
233
234 /// [`ImageList_GetBkColor`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_getbkcolor)
235 /// function.
236 #[must_use]
237 pub fn GetBkColor(&self) -> COLORREF {
238 unsafe { COLORREF::from_raw(ffi::ImageList_GetBkColor(self.ptr())) }
239 }
240
241 /// [`ImageList_GetIcon`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_geticon)
242 /// function.
243 ///
244 /// A copy of the stored icon is returned.
245 #[must_use]
246 pub fn GetIcon(&self, index: u32, flags: co::ILD) -> HrResult<DestroyIconGuard> {
247 unsafe {
248 match ptr_to_option_handle(ffi::ImageList_GetIcon(self.ptr(), index as _, flags.raw()))
249 {
250 None => Err(co::HRESULT::E_FAIL),
251 Some(h) => Ok(DestroyIconGuard::new(h)),
252 }
253 }
254 }
255
256 /// [`ImageList_GetIconSize`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_geticonsize)
257 /// function.
258 #[must_use]
259 pub fn GetIconSize(&self) -> HrResult<SIZE> {
260 let mut sz = SIZE::default();
261 match unsafe { ffi::ImageList_GetIconSize(self.ptr(), &mut sz.cx, &mut sz.cy) } {
262 0 => Err(co::HRESULT::E_FAIL),
263 _ => Ok(sz),
264 }
265 }
266
267 /// [`ImageList_GetImageCount`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_getimagecount)
268 /// function.
269 #[must_use]
270 pub fn GetImageCount(&self) -> u32 {
271 unsafe { ffi::ImageList_GetImageCount(self.ptr()) as _ }
272 }
273
274 /// [`ImageList_Remove`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_remove)
275 /// function.
276 pub fn Remove(&self, index: Option<u32>) -> HrResult<()> {
277 match unsafe { ffi::ImageList_Remove(self.ptr(), index.map_or(-1, |i| i as _)) } {
278 0 => Err(co::HRESULT::E_FAIL),
279 _ => Ok(()),
280 }
281 }
282
283 /// [`ImageList_ReplaceIcon`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_replaceicon)
284 /// function.
285 ///
286 /// A copy of the icon is made and stored in the image list, so you're free
287 /// to release the original icon.
288 pub fn ReplaceIcon(&self, index: u32, hicon_new: &HICON) -> HrResult<u32> {
289 match unsafe { ffi::ImageList_ReplaceIcon(self.ptr(), index as _, hicon_new.ptr()) } {
290 -1 => Err(co::HRESULT::E_FAIL),
291 idx => Ok(idx as _),
292 }
293 }
294
295 /// [`ImageList_SetBkColor`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_setbkcolor)
296 /// function.
297 pub fn SetBkColor(&self, bk_color: Option<COLORREF>) -> Option<COLORREF> {
298 match unsafe { ffi::ImageList_SetBkColor(self.ptr(), bk_color.unwrap_or_default().raw()) } {
299 CLR_NONE => None,
300 c => Some(unsafe { COLORREF::from_raw(c) }),
301 }
302 }
303
304 /// [`ImageList_SetImageCount`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_setimagecount)
305 /// function.
306 ///
307 /// # Safety
308 ///
309 /// If the size is increased, you must call
310 /// [`HIMAGELIST::ReplaceIcon`](crate::HIMAGELIST::ReplaceIcon) to fill the
311 /// new indexes, otherwise draw operations will be
312 /// unpredictable.
313 pub unsafe fn SetImageCount(&self, new_count: u32) -> HrResult<()> {
314 match unsafe { ffi::ImageList_SetImageCount(self.ptr(), new_count) } {
315 0 => Err(co::HRESULT::E_FAIL),
316 _ => Ok(()),
317 }
318 }
319
320 /// [`ImageList_Write`](https://learn.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-imagelist_write)
321 /// function.
322 pub fn Write(&self, stream: &impl ole_IStream) -> HrResult<()> {
323 match unsafe { ffi::ImageList_Write(self.ptr(), stream.ptr()) } {
324 0 => Err(co::HRESULT::E_FAIL),
325 _ => Ok(()),
326 }
327 }
328}